package service

import (
	"fmt"
	"ginvueadmin/global"
	"ginvueadmin/models"
)

// 获取动态菜单树
func GetMenuTree(authorityId string) (menus []models.SysMenu, err error) {
	/*
		1. 通过 authorityId 的参数，调用 getMenuTreeMap 获取根节点菜单
		2. 从 menuTree 中以键 "0" 获取数据，并赋值给 menus 变量，获取顶层菜单
		3. 遍历从 2 中获取的顶层菜单 menus
		4. 获取子级菜单。调用 getChildrenList 方法获取，传入取地址的 menus 绑定
		5. 返回 menus 与 err
	*/

	menuTree, err := getMenuTreeMap(authorityId)
	menus = menuTree["0"]
	fmt.Println("menus:", menus)

	for i := 0; i < len(menus); i++ {
		err = getChildrenList(&menus[i], menuTree)
	}

	return menus, err
}

// 获取路由总树 map
func getMenuTreeMap(authorityId string) (treeMap map[string][]models.SysMenu, err error) {
	/*
		1. 定义一个 allMenus 的 SysMenu 结构体变量，用于存储 treeMap
		2. 使用 make 声明键为 string，值为 SysMenu 的空 map
		3. 通过 authorityId 查询 sys_menus 表，并绑定 allMenus
		4. 遍历查询出来的 allMenus，存入需要的 treeMap 中

		1. 声明了一个 allMenus 变量，用于存储从数据库中查询出来的所有菜单数据。
		2. 使用 make 函数初始化了 treeMap，它是一个 map[string][]model.SysMenu 类型的变量，用于存储菜单树的结构。其中，string 类型的键表示父菜单的 ID，[]model.SysMenu 类型的值表示该父菜单下的子菜单列表。
		3. 调用 global.DB 对象的方法进行数据库查询操作，根据给定的 authorityId 条件查询菜单数据，并按照 sort 字段进行排序。同时，使用 Preload("Parameters") 预加载相关联的参数数据。
		4. 使用 for 循环遍历 allMenus 切片中的每个菜单项 v。
		5. 在循环中，将当前菜单 v 添加到 treeMap[v.ParentId] 中，即将其作为父菜单 v.ParentId 对应的子菜单列表中的一项。使用 append 函数来实现将菜单项添加到切片中。
		6. 最后，函数返回错误值 err 和菜单树 treeMap。
	*/

	var allMenus []models.SysMenu
	treeMap = make(map[string][]models.SysMenu)

	err = global.DB.Where("authority_id", authorityId).Order("sort").Preload("Parameters").Find(&allMenus).Error
	fmt.Println("allMenus:", allMenus)
	for _, v := range allMenus {
		treeMap[v.ParentId] = append(treeMap[v.ParentId], v)
	}

	return treeMap, err
}

// 获取子菜单
func getChildrenList(menu *models.SysMenu, treeMap map[string][]models.SysMenu) (err error) {
	menu.Children = treeMap[menu.MenuId]

	for i := 0; i < len(menu.Children); i++ {
		err = getChildrenList(&menu.Children[i], treeMap)
	}

	return err
}
